package cn.xingzhe.monster.user.application.service.impl;

import cn.xingzhe.monster.user.application.service.CaptchaApplicationService;
import cn.xingzhe.monster.user.domain.enums.CaptchaTypeEnum;
import cn.xingzhe.monster.user.domain.model.CaptchaModel;
import cn.xingzhe.monster.user.domain.service.CaptchaDomainService;
import cn.xingzhe.monster.user.domain.service.MessageSender;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 验证码应用服务实现
 * 协调领域服务和基础设施服务完成验证码发送
 *
 * @author System
 * @version 1.0.0
 * @since 2024-01-01
 */
@Service
public class CaptchaApplicationServiceImpl implements CaptchaApplicationService {

    private final CaptchaDomainService captchaDomainService;
    private final List<MessageSender> messageSenders;

    public CaptchaApplicationServiceImpl(CaptchaDomainService captchaDomainService,
                                         List<MessageSender> messageSenders) {
        this.captchaDomainService = captchaDomainService;
        this.messageSenders = messageSenders;
    }

    @Override
    public void sendCaptcha(String key, Integer typeCode) {
        // 1. 转换验证码类型
        CaptchaTypeEnum type = CaptchaTypeEnum.getByCode(typeCode);
        if (type == null) {
            throw new IllegalArgumentException("验证码类型无效");
        }

        // 2. 生成验证码（调用领域服务）
        CaptchaModel captchaModel = captchaDomainService.generateCaptcha(key, type);
        String code = captchaModel.getCode();

        // 3. 查找支持的消息发送器并发送验证码
        MessageSender sender = findMessageSender(key);
        if (sender == null) {
            throw new IllegalArgumentException("邮箱或手机号格式不正确");
        }

        // 4. 发送验证码
        sender.sendCaptcha(key, code, type);
    }

    /**
     * 查找支持指定接收者的消息发送器
     *
     * @param recipient 接收者（邮箱或手机号）
     * @return 消息发送器，如果未找到则返回null
     */
    private MessageSender findMessageSender(String recipient) {
        return messageSenders.stream()
                .filter(sender -> sender.supports(recipient))
                .findFirst()
                .orElse(null);
    }
}

